Skip to content

SWIG 包装 std::size_t 报 Fragment not found 排查 ​

用 SWIG 给 C++ 库生成 Python 绑定,接口里一旦出现 size_t——无论是 std::pair<bool, size_t> 还是 std::vector<size_t>——Python 侧拿到的就是打不开的 SwigPyObject,编译期还会伴随 Fragment 'SWIG_AsVal_std_size_t' not found 警告。这篇记录完整的排查过程、根因和当前可用的 workaround。

问题现象 ​

.i 接口文件里已经用 %template 声明了模板实例:

swig
%template(BoolSizeTPair) std::pair<bool, size_t>;

生成与编译都能通过,但 Python 侧调用返回 pair 的接口时报错:

cannot unpack non-iterable SwigPyObject object

返回值没有被打包成 Python 元组,而是一个裸的 SwigPyObject——说明 SWIG 没有为这个类型生成正确的转换代码。

排查过程 ​

怀疑是 size_t 的命名空间形式影响匹配,把模板实例化改为显式的 std::size_t:

swig
%template(BoolSizeTPair) std::pair<bool, std::size_t>;

这次编译器给出了更有价值的线索——两条警告:

swig.i:221: Warning 490: Fragment 'SWIG_AsVal_std_size_t' not found.
swig.i:221: Warning 490: Fragment 'SWIG_From_std_size_t' not found.

Fragment 是 SWIG typemap 系统里的类型转换代码片段。SWIG_AsVal_std_size_t / SWIG_From_std_size_t 找不到,意味着 SWIG 不知道如何在 std::size_t 与目标语言类型之间转换。

根因 ​

在 swig/swig#1712 中,维护者 wsfulton 确认了根因:std::size_t 只在 C++ 头文件 <cstddef> 中定义,而 SWIG 的库文件目录里没有对应的 cstddef.i,类型信息缺失导致 fragment 查找失败。

值得注意的是,截至该 issue 最近的讨论(2025 年 10 月),官方修复仍处于推迟状态——%apply 方式对 Python 目标不生效,typedef 方式又触发 SwigType_type() 的无限递归 bug,因此升级 SWIG 版本目前解决不了这个问题。该问题还可能影响 octave、r、ruby、scilab 等其他目标语言。

解决方案 ​

issue 中由报告者提出、维护者认可的 workaround,是在 .i 文件中把全局 ::size_t 引入 std 命名空间:

swig
namespace std {
  typedef ::size_t size_t;
}

这样 SWIG 在解析 std::size_t 时能关联到已知的全局 size_t 类型,fragment 查找即可命中。(该写法来自 issue 讨论,使用前建议在自己的工程里验证。)

另一路尝试及其局限 ​

SWIG 1.3 官方文档在讲基本类型时给过另一种处理 size_t 的思路(SWIG.html#SWIG_nn20):

swig
%inline %{
typedef long unsigned int size_t;
%}

namespace std {
  %template(VecSize) vector<size_t>;
}

注意 %inline 只是把 typedef 插入生成的包装代码,并不等同于向 SWIG 声明 std::size_t 这个类型;对 std:: 限定形式触发的 fragment 缺失,这条路径未必有效。issue #1712 中也未讨论该写法,优先采用上一节的 namespace std 方案。

小结 ​

SWIG 绑定中 size_t 相关模板报 Fragment 'SWIG_AsVal_std_size_t' not found 或 Python 侧拿到裸 SwigPyObject,根因是 SWIG 缺少 cstddef.i、没有 std::size_t 的类型信息。当前版本的可行解法是在接口文件里加 namespace std { typedef ::size_t size_t; };官方修复截至 2025 年 10 月仍未合入,升级版本无效。

参考 ​

最近更新

基于 VitePress 构建